package DatabaseManaging;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;

import org.apache.log4j.Logger;

import Autodesk.CheckWebservice;
import Autodesk.ParseLogs;
import DatabaseManaging.DatabaseManager;


public abstract class DatabaseChecker {
	private static Logger logger = Logger.getLogger(ParseLogs.class);
	private ParametersDAO jdbc;
	
	public DatabaseChecker(){
		
	}
	
	public ParametersDAO getJdbc() {
		return jdbc;
	}
	public void setJdbc(ParametersDAO jdbc) {
		this.jdbc = jdbc;
	}
	public DatabaseChecker(ParametersDAO jdbc) {
		this.jdbc = jdbc;
	}
	public boolean CompareAbbs(String abProductDocument, String abProductList) {
		String[] abProductDocSpl=abProductDocument.split("\t");
		String[] abProducListSP=abProductList.split("\t");
		for(int j=2;j<7 && !abProducListSP[j].equals("");j++){
			boolean founded=false;
			for(int i=2;i<7 && !abProductDocSpl[i].equals("");i++){
				if(abProductDocSpl[i].equals(abProducListSP[j])){
					founded=true;
				}
			}
			if(founded==false){
				return false;
			}
				
		}
		return true;
				
	}
	public String extractAbbs(String abProductDocument, String abProductList) {
		String abs="";
		ArrayList<String> listAbs=new ArrayList<String>();
		String[] abProductDocSpl=abProductDocument.split("\t");
		String[] abProductListSP=abProductList.split("\t");
		for(int i=2;i<7 && !abProductDocSpl[i].equals("");i++){
			listAbs.add(abProductDocSpl[i]);
		}
		
		for(int j=2;j<7 && !abProductListSP[j].equals("");j++){
			if(!listAbs.contains(abProductListSP[j])){
				listAbs.add(abProductListSP[j]);
			}
		}
		for(int i=0;i<listAbs.size();i++){
			abs=abs+listAbs.get(i)+"\t";
		}
		return abs;				
	}

	public void updateDatabase(String abs,String product_id) {
		String[] absSp= abs.split("\t");
		String query="UPDATE akn_product_dim SET";
		for(int i=0;i<absSp.length;i++){
			 query=query+" product_abbr"+Integer.toString(i+1)+"='"+absSp[i]+"'";
			 if(i!=absSp.length-1){
				 query=query+",";
			 }
		}
		query=query+" WHERE product_dim_id ="+product_id+";";
		DatabaseManager db=new DatabaseManager();
		db.executeQuery(query);
		logger.info("QUERY: "+query);
		logger.info("Succesfully Inserted.");
	}
	
	/**
	 * @param listnewRegs
	 * @param documentLine
	 * @return Returns a value if the name of an elements in the list is equal to the name passed by parameter , and returns "0" in other case.
	 */
	public String findRepeated(ArrayList<String> listnewRegs,
			String documentLine) {
		// TODO Auto-generated method stub
		String result="0";
		String[] docSplitted=documentLine.split("\t");
		String product=docSplitted[1];
		String[] valueSplitted=null;
		for(int i=0;i<listnewRegs.size();i++){
			valueSplitted=listnewRegs.get(i).split("\t");
			if(product.equals(valueSplitted[1])){
				result=listnewRegs.get(i);
				return result;
			}

		}
		return result;
	}
	
	/**
	 * @param parciaList
	 * @param mappingFile
	 * @param checker
	 * @return Alters elements which don't have all the abbreviations required in the database and in the mapping document. And, remove from the list which will be inserted to the database, the elements which have been stored in the database before.
	 * @throws IOException
	 */
	public ArrayList<String> findExistenceDatabase(
			ArrayList<String> parciaList, File mappingFile,CheckWebservice checker) throws IOException {
		String documentLine=null;
		String abs;
		BufferedReader fisMapDoc=new BufferedReader(new FileReader(mappingFile));
		File tempFile=new File(mappingFile.getAbsoluteFile()+".tmp");
		PrintWriter pw=new PrintWriter(new FileWriter(tempFile));
		while ((documentLine = fisMapDoc.readLine()) != null) {
			String[] docLineSp=documentLine.split("\t");
			String productList=this.findRepeated(parciaList, documentLine);
			if(!productList.equals("0")){
				String [] productListSplit=productList.split("\t");
				if(productListSplit[8].equals(docLineSp[8])){//Compare Releases
					if(!this.CompareAbbs(documentLine, productList)){
						logger.info("FIND REPEATED:"+productList+"-"+documentLine);
						abs=this.extractAbbs(documentLine, productList);
						String line=checker.writeProductLine(docLineSp[1], abs, docLineSp[7], docLineSp[8],docLineSp[0]);
						pw.println(line);
						
						logger.info("UPDATED:"+documentLine);
						this.updateDatabase(abs, docLineSp[0]);
					}else{
						pw.println(documentLine);
					}
					parciaList.remove(productList);
					logger.info("REMOVED FROM LIST:"+productList);
					logger.info("-------------------------------------------");
					}else{
						if(!this.CompareAbbs(documentLine, productList)){
							logger.info("FIND REPEATED:"+productList+"-"+documentLine);
							abs=this.extractAbbs(documentLine, productList);
							
							String docline=checker.writeProductLine(docLineSp[1], abs, docLineSp[7], docLineSp[8],docLineSp[0]);
							pw.println(docline);
							logger.info("WRITTEN in the doc: "+docline);
	
							String productAddedAbb=checker.writeProductLine(productListSplit[1], abs, productListSplit[7], productListSplit[8],productListSplit[0]);
							if(!parciaList.remove(productList)){
								System.out.print("CAN NOT REMOVE THE ELEMNT");
								logger.info(productList);
							}
							parciaList.add(productAddedAbb);
							logger.info("ADDED TO LIST:"+productAddedAbb);
							
							this.updateDatabase(abs, docLineSp[0]);
							logger.info("UPDATED:"+documentLine);
							logger.info("-------------------------------------------");
						}else{
							pw.println(documentLine);
						}
				}
			}else{
				pw.println(documentLine);
			}
		}
		pw.close();
		fisMapDoc.close();
		if (!mappingFile.delete()) {
	        logger.info("Could not delete file");
	      }       
	      //Rename the new file to the filename the original file had.
	      if (!tempFile.renameTo(mappingFile)){
	        logger.info("Could not rename file");
		}
		return parciaList;
	}
	/**
	 * @param parciaList
	 * @param mappingFile
	 * @param checker
	 * @return Alters elements which don't have all the abbreviations required in the database and in the mapping document. And, remove from the list which will be inserted to the database, the elements which have been stored in the database before.
	 * @throws IOException
	 */
	public ArrayList<String> findExistenceDatabase(
			ArrayList<String> parciaList, File mappingFile) throws IOException {
		String documentLine=null;
		String abs;
		BufferedReader fisMapDoc=new BufferedReader(new FileReader(mappingFile));
		File tempFile=new File(mappingFile.getAbsoluteFile()+".tmp");
		PrintWriter pw=new PrintWriter(new FileWriter(tempFile));
		while ((documentLine = fisMapDoc.readLine()) != null) {
			String[] docLineSp=documentLine.split("\t");
			String productList=this.findRepeated(parciaList, documentLine);
			if(!productList.equals("0")){
				this.checkDatabase(parciaList, documentLine, pw, docLineSp,
						productList);
			}else{
				pw.println(documentLine);
			}
		}
		pw.close();
		fisMapDoc.close();
		if (!mappingFile.delete()) {
	        logger.info("Could not delete file");
	     }       
	      //Rename the new file to the filename the original file had.
	      if (!tempFile.renameTo(mappingFile)){
	        logger.info("Could not rename file");
		}
		return parciaList;
	}
	
//	public abstract String findRepeated(ArrayList<String> parciaList,
//			String documentLine);

	public abstract void checkDatabase(ArrayList<String> parciaList,
			String documentLine, PrintWriter pw, String[] docLineSp,
			String productList);
	
	/////////////////////////////////////////LAST UPDATE////////////////////
	
	public void updateDatabase(
			ArrayList<String> parciaList) throws IOException {
		for(int i=0;i<parciaList.size();i++){			
			Object element=this.getElement(parciaList.get(i));			
			ArrayList<Object> listDBWithEqName=findEqualsName(element);
			
			if(!listDBWithEqName.isEmpty()){
				element=updateRegister(listDBWithEqName,element);
				updateDatabase(listDBWithEqName,element);
			}
			InsertIfitIsNOTRepeated(listDBWithEqName,element);
			
		}
		
	}
	

	public abstract Object getElement(String elementName);
	public abstract ArrayList<Object> findEqualsName(Object element) ;
	public abstract void InsertIfitIsNOTRepeated(ArrayList<Object> listDBWithEqName,Object elementToInsert);
	public abstract void updateDatabase(ArrayList<Object> listDBWithEqName,Object element) ;
	public abstract Object updateRegister(ArrayList<Object> listDBWithEqName,Object element) ;

}
